﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;

namespace navi_npc_ch_chunkspy_converter
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 输入文本是navi_npc_ch.txt（用chunkspy反编译lub后整理出来）
        /// 输出文本是npcdata1.txt
        /// 用户自定义文本是npcdata2.txt
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_go_Click(object sender, EventArgs e)
        {
            //onenpc存储一个npc的数据，共有8个参数，分别是：mapname、未知1、未知2、SpriteID、NpcName、未知3、x坐标、y坐标
            string[] onenpc;
            //npcpack存储所有onenpc的集合
            List<string[]> npcpack = new List<string[]>();
            using (StreamReader sr = new StreamReader("navi_npc_ch.txt", Encoding.GetEncoding("GB2312")))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    if (line.StartsWith("array=")) continue;
                    if (line.StartsWith("index ")) continue;
                    onenpc = new string[8];
                    onenpc[0] = line;
                    onenpc[0] = onenpc[0].Remove(0, 1);
                    onenpc[0] = onenpc[0].Remove(onenpc[0].Length-1, 1);    //删除mapname两头的引号
                    onenpc[1] = sr.ReadLine();  //读入未知1
                    onenpc[2] = sr.ReadLine();  //读入未知2
                    onenpc[3] = sr.ReadLine();  //读入SpriteID
                    onenpc[4] = sr.ReadLine();  //读入NpcName
                    onenpc[4] = onenpc[4].Remove(0, 1);
                    onenpc[4] = onenpc[4].Remove(onenpc[4].Length-1, 1);    //删除NpcName两头的引号
                    onenpc[5] = sr.ReadLine();  //读入未知3
                    onenpc[6] = sr.ReadLine();  //读入x坐标
                    onenpc[7] = sr.ReadLine();  //读入y坐标
                    npcpack.Add(onenpc);
                }
                //将npc格式化成单行、tab分隔的文件
                StreamWriter sw = new StreamWriter("navi_npc_ch_out.txt", false, Encoding.GetEncoding("GB2312"), 10240);
                sw.WriteLine("mapname\tunknow1\tunknow2\tSpriteID\tNpcName\tunknow3\tx\ty");
                foreach (string[] npc in npcpack)
                {
                    sw.WriteLine(npc[0] + "\t" + npc[1] + "\t" + npc[2] + "\t" + npc[3] + "\t" + npc[4] + "\t" + npc[5] + "\t" + npc[6] + "\t" + npc[7]);
                }
                sw.Close();
            }
            err.Text += npcpack.Count.ToString() + " npcs done";
        }

        /// <summary>
        /// 加密npcdata1.txt和npcdata2.txt,输出是npcdata1.dat和ncpdata2.dat
        /// key=24byte,iv=8byte
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_encrypt_Click(object sender, EventArgs e)
        {
            err.Text = "";
            TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
            tdes.GenerateIV();
            tdes.GenerateKey();
            err.Text += "new byte[] {";
            //在顶端加入16字节随机数
            Random rnd = new Random();
            for (int i = 0; i < 16; i++)
            {
                err.Text += rnd.Next(256).ToString() + ",";
            }
            //输出iv
            foreach (byte tmpbyte in tdes.IV)
            {
                err.Text += tmpbyte.ToString() + ",";
            }
            //在中间加入8字节随机数
            for (int i = 0; i < 8; i++)
            {
                err.Text += rnd.Next(256).ToString() + ",";
            }
            //输出key
            foreach (byte tmpbyte in tdes.Key)
            {
                err.Text += tmpbyte.ToString() + ",";
            }
            //在最后加入32字节随机数
            for (int i = 0; i < 32; i++)
            {
                err.Text += rnd.Next(256).ToString() + ",";
            }
            err.Text = err.Text.Remove(err.Text.Length - 1, 1);
            err.Text += "}";
            byte[] a = new byte[] { 11, 13, 14, 15, 255 };
        }

        private void EncryptData(String inName, String outName, string keyiv)
        {
            string[] tmpstr = keyiv.Split(',');
            byte[] tdesKey = new byte[24];
            byte[] tdesIV = new byte[8];
            for (int i = 0; i < tmpstr.Length; i++)
            {
                if (i == 16)
                {
                    for (int x = 0; x < 8; x++)
                    {
                        tdesIV[x] = byte.Parse(tmpstr[i]);
                        i++;
                    }
                }
                if (i == 32)
                {
                    for (int y = 0; y < 24; y++)
                    {
                        tdesKey[y] = byte.Parse(tmpstr[i]);
                        i++;
                    }
                }
            }
            //test ,output key/iv
            tb_keyiv.Text += "\r\n";
            foreach (byte iii in tdesIV)
            {
                tb_keyiv.Text += iii.ToString() + ",";
            }
            tb_keyiv.Text += "\r\n";
            foreach (byte kkk in tdesKey)
            {
                tb_keyiv.Text += kkk.ToString() + ",";
            }
            //Create the file streams to handle the input and output files.
            FileStream fin = new FileStream(inName, FileMode.Open, FileAccess.Read, FileShare.None, 10240);
            FileStream fout = new FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 10240);
            fout.SetLength(0);

            //Create variables to help with read and write.
            byte[] bin = new byte[1000]; //This is intermediate storage for the encryption.
            long rdlen = 0;              //This is the total number of bytes written.
            long totlen = fin.Length;    //This is the total length of the input file.
            int len;                     //This is the number of bytes to be written at a time.
            TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
            CryptoStream encStream = new CryptoStream(fout, tdes.CreateEncryptor(tdesKey, tdesIV), CryptoStreamMode.Write);
            //Read from the input file, then encrypt and write to the output file.
            while (rdlen < totlen)
            {
                len = fin.Read(bin, 0, 1000);
                encStream.Write(bin, 0, len);
                rdlen = rdlen + len;
                err.Text += "\r\n" + rdlen.ToString() + " bytes encrypted:";
            }
            encStream.Close();
            fin.Close();
            fout.Close();
        }

        //解密数据
        private string DEncryptData(String inName, string keyiv)
        {
            string[] tmpstr = keyiv.Split(',');
            byte[] tdesKey = new byte[24];
            byte[] tdesIV = new byte[8];
            for (int i = 0; i < tmpstr.Length; i++)
            {
                if (i == 16)
                {
                    for (int x = 0; x < 8; x++)
                    {
                        tdesIV[x] = byte.Parse(tmpstr[i]);
                        i++;
                    }
                }
                if (i == 32)
                {
                    for (int y = 0; y < 24; y++)
                    {
                        tdesKey[y] = byte.Parse(tmpstr[i]);
                        i++;
                    }
                }
            }
            //test ,output key/iv
            tb_keyiv.Text += "\r\n";
            foreach (byte iii in tdesIV)
            {
                tb_keyiv.Text += iii.ToString() + ",";
            }
            tb_keyiv.Text += "\r\n";
            foreach (byte kkk in tdesKey)
            {
                tb_keyiv.Text += kkk.ToString() + ",";
            }
            //Create the file streams to handle the input and output files.
            FileStream fin = new FileStream(inName, FileMode.Open, FileAccess.Read, FileShare.None, 10240);
            //FileStream fout = new FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 10240);
            MemoryStream fout = new MemoryStream();
            fout.SetLength(0);

            //Create variables to help with read and write.
            byte[] bin = new byte[1000]; //This is intermediate storage for the encryption.
            long rdlen = 0;              //This is the total number of bytes written.
            long totlen = fin.Length;    //This is the total length of the input file.
            int len;                     //This is the number of bytes to be written at a time.
            TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
            CryptoStream encStream = new CryptoStream(fout, tdes.CreateDecryptor(tdesKey, tdesIV), CryptoStreamMode.Write);
            //Read from the input file, then encrypt and write to the output file.
            while (rdlen < totlen)
            {
                len = fin.Read(bin, 0, 1000);
                encStream.Write(bin, 0, len);
                rdlen = rdlen + len;
                err.Text += "\r\n" + rdlen.ToString() + " bytes dencrypted:";
            }
            encStream.Close();
            byte[] b = fout.ToArray();
            string result = Encoding.GetEncoding("GB2312").GetString(b, 0, b.Length);
            fin.Close();
            fout.Close();
            return result;
        }

        //解密文本
        private void btn_dencrypt_Click(object sender, EventArgs e)
        {
            err.Text += "\r\n" + DEncryptData("npcdata2.dat", tb_keyiv.Text);
        }

        private void btn_encrypt_Click_1(object sender, EventArgs e)
        {
            EncryptData("npcdata1.txt", "npcdata1.dat", tb_keyiv.Text);
            EncryptData("npcdata2.txt", "npcdata2.dat", tb_keyiv.Text);
        }

        private void btn_process_idnum2itemdisplaynametable_Click(object sender, EventArgs e)
        {
            //load itemslotcounttable to memory
            List<string> itemslotarray1 = new List<string>();
            List<string> itemslotarray2 = new List<string>();
            using (StreamReader sr = new StreamReader("itemslotcounttable.txt", Encoding.GetEncoding("GB2312")))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    string[] tmparray = line.Split('#');
                    if (tmparray.Length > 1)
                    {
                        itemslotarray1.Add(tmparray[0]);
                        itemslotarray2.Add(tmparray[1]);
                    }
                }
            }
            //edit idnum2itemdisplaynametable.txt
            StreamReader sr2 = new StreamReader("idnum2itemdisplaynametable.txt.source", Encoding.GetEncoding("GB2312"));
            StreamWriter sw = new StreamWriter("num2itemdisplaynametable.txt", false, Encoding.GetEncoding("GB2312"), 102400);
            string line2;
            string line3="xxxxxxxxxx";
            bool foundslots = false;
            while ((line2 = sr2.ReadLine()) != null)
            {
                foundslots = false;
                string[] tmparray2 = line2.Split('#');
                if (tmparray2.Length > 1)
                {
                    for(int i=0;i<itemslotarray1.Count;i++)
                    {
                        if (tmparray2[0] == itemslotarray1[i])
                        {
                            line3 = tmparray2[0] + "#" + tmparray2[1] + "(" + itemslotarray2[i] + "洞)#";
                            foundslots = true;
                            break;
                        }
                    }
                    if (foundslots) { sw.WriteLine(line3); } else { sw.WriteLine(line2); }
                }
                else
                {
                    sw.WriteLine(line2);
                }
            }
            sr2.Close();
            sw.Close();
            MessageBox.Show("done");
        }
    }
}
